import java.util.Map;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import org.rsbot.event.events.ServerMessageEvent;
import org.rsbot.event.listeners.PaintListener;
import org.rsbot.event.listeners.ServerMessageListener;
import org.rsbot.script.Script;
import org.rsbot.script.ScriptManifest;
import org.rsbot.script.wrappers.RSNPC;
import org.rsbot.script.wrappers.RSTile;
import org.rsbot.script.wrappers.RSArea;
import org.rsbot.script.wrappers.RSPlayer;
import org.rsbot.script.wrappers.RSObject;
import org.rsbot.script.wrappers.RSItem;
import org.rsbot.script.wrappers.RSInterface;
import org.rsbot.script.wrappers.RSComponent;
import org.rsbot.script.methods.Skills;
import org.rsbot.script.methods.Bank;
import org.rsbot.script.methods.Camera;
import org.rsbot.script.methods.Players;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

@ScriptManifest(authors = {"hah_rs"}, name = "Crafting Guild Miner", version = 1.6, 
description = ("Mines gold and silver in crafting guild"))
              
public class CraftingGuildMiner extends Script implements PaintListener, ServerMessageListener {
    
public int fallyBoothID = 11758;
public int draynorBoothID = 2213;
public int boothID;
public int guildDoorID = 2647;
public int goldMined = 0, silverMined = 0;
public int gemsFound = 0;
public boolean passedMusician = false;
public boolean hasBanked = false;

public long timeRunning = 0, hours = 0, minutes = 0, seconds = 0, startTime = System.currentTimeMillis();
public int startexp, exp, expGained;
public float expsec, expmin, exphour;

public RSTile[] pathCabbageToBank = { new RSTile(3065, 3277), new RSTile(3072, 3267),
                                    new RSTile(3076, 3257), new RSTile(3085, 3250),
                                    new RSTile(3092, 3245) };

public RSTile[] pathCabbageToGuild = { new RSTile(3044, 3277), new RSTile(3031, 3278),
                                    new RSTile(3020, 3277), new RSTile(3007, 3279),
                                    new RSTile(2994, 3283), new RSTile(2981, 3283),
                                    new RSTile(2967, 3287), new RSTile(2954, 3293),
                                    new RSTile(2942, 3298), new RSTile(2933, 3289)};

public RSArea guildArea  = new RSArea(new RSTile(2928, 3276), new RSTile(2943, 3288));
public RSArea guildArea2 = new RSArea(new RSTile(2936, 3289), new RSTile(2943, 3291));
public RSArea bankArea   = new RSArea(new RSTile(3009, 3355), new RSTile(3018, 3360));
public RSArea mineArea   = new RSArea(new RSTile(2937, 3276), new RSTile(2943, 3291));
public RSArea draynorArea = new RSArea(new RSTile(3087, 3239), new RSTile(3098, 3247));
public RSArea wallArea = new RSArea(new RSTile(3005, 3321), new RSTile(3008, 3325));
public RSArea musicianArea = new RSArea(new RSTile(3019, 3279), new RSTile(3015, 3276));
public RSArea cabbageArea = new RSArea(new RSTile(3055, 3290), new RSTile(3049, 3285));

public int[] rocksID = { 11186,11187, 11188, 11183,11184,11185 } ;

public RSObject door;
public RSObject gate;
public RSObject ore, nextOre;
public int currentID;
public RSTile oreLocation, nextOreLocation;
public RSTile cabbageTile = new RSTile(3054, 3289);
public RSTile gateTile = new RSTile(3053, 3283);
public RSTile musicianTile = new RSTile(3017,3278);
public RSTile wallTile = new RSTile(3007,3323);
public RSTile doorTile = new RSTile(2933,3289);
public RSTile bankTile = new RSTile(3012,3355);

public boolean useCabbagePort = false;

// GUI
private JCheckBox Ringbutton;
private JCheckBox RockStealbutton;
private JButton StartButton;
SCRIPTGUI gui;


public boolean onStart() { 
    log("Start at bank or guild");  
    gui = new SCRIPTGUI();
    gui.setVisible(true);
    while (gui.isVisible()) {
        sleep(2000);
    }

    if (Ringbutton.isSelected()) {
        log("Using cabbage port to draynor way");
        boothID = draynorBoothID;
    useCabbagePort = true;
    } else {
        log("Using guild to fally way");
        boothID = fallyBoothID;
    useCabbagePort = false;
    }
    walking.setRun(true);
    startexp = skills.getCurrentExp(Skills.MINING);  
    mouse.setSpeed(random(7, 8));   
    return true;
}

public void antiBan() {
    if (random(1, 12) == 1) {
        camera.setAngle(random(1, 359));
    }

    if (random(1, 11) == 1) {
        final int x = (int) mouse.getLocation().getX();
        final int y = (int) mouse.getLocation().getY();
        mouse.move(x + random(-100, 100), y + random(-50, 50));
    }
    if (random(1, 60) == 1) {
        game.openTab(game.TAB_STATS);
        mouse.move(random(678, 731), random(210, 231));
        sleep(random(731, 2313));
       game.openTab(game.TAB_INVENTORY);
    }
}

private boolean atGuild(){
    if ( guildArea.contains(getMyPlayer().getLocation()) || guildArea2.contains(getMyPlayer().getLocation()) ) {
        return true;
    } else return false;
}

private boolean atGuild2(){
    return guildArea2.contains(getMyPlayer().getLocation());
}

private boolean atFallyBank(){
    return bankArea.contains(getMyPlayer().getLocation());
}

private boolean atDraynorBank(){
    return draynorArea.contains(getMyPlayer().getLocation());
}

private boolean atWall(){
    return wallArea.contains(getMyPlayer().getLocation());
}

private boolean atMusician(){
    return musicianArea.contains(getMyPlayer().getLocation());
}

private boolean atCabbage(){
    return cabbageArea.contains(getMyPlayer().getLocation());
}

private boolean atTheBank(){
    if ( useCabbagePort )
        return atDraynorBank();
    else
        return atFallyBank();
}

private void cabbageToBank(){
    RSTile[] randomizedPath = walking.randomizePath(pathCabbageToBank, 2, 2);
    //return walking.walkPathMM(randomizedPath);
    RSTile t = walking.getDestination();
    if(t != null){
        if(calc.distanceTo(t) < 5){
        walking.walkTileMM(walking.nextTile(randomizedPath));
        return;
        }
    }
    walking.walkTileMM(walking.nextTile(randomizedPath));
}

private void cabbagePort() {
    camera.setCompass('s');
    sleep(random(800,1300));
    RSItem ring = equipment.getItem(equipment.RING);
    if (game.getCurrentTab() != game.TAB_EQUIPMENT)
        game.openTab(game.TAB_EQUIPMENT);
    else if (game.getCurrentTab() == game.TAB_EQUIPMENT)
        ring.doAction("Cabbage-port");
    sleep(random(600,1000));
}

private void openDoor() {
    door = objects.getNearest(guildDoorID);
    if ( !(door == null) ){
        if(!door.isOnScreen() && !(getMyPlayer().isMoving()) ){
            walking.walkTileMM(new RSTile(2933, 3288));
        }

        if ( !getMyPlayer().isMoving() && !getMyPlayer().getLocation().equals(doorTile) ) {
            door.doAction("Open Guild Door");
            sleep(random(700, 1100));
        }
    }
}

private void openDoorCheck() {
    RSObject door = objects.getNearest(guildDoorID);

    if ( !(door == null) ){
        if ( !getMyPlayer().isMoving() && !atGuild() ) {
            door.doAction("Open Guild Door");
            sleep(random(700,1100));
        }
    }
}

private void depositOres() {
    RSObject bankBooth = objects.getNearest(boothID);

    camera.setPitch(true);
    if ( !getMyPlayer().isMoving() && !(interfaces.get(Bank.INTERFACE_BANK).isValid()) ) {
        bankBooth.doAction("Use-quickly Bank booth");
        sleep(random(500,800));
    }

    if(interfaces.get(Bank.INTERFACE_BANK).isValid() && inventory.isFull() ) {
        log("depositing items");
        bank.depositAll();
        sleep(random(500,900)); 
        while ( bank.isOpen() ) {
           bank.close();
           sleep(random(100,300)); 
        }
        hasBanked = true;
    }
}

public RSObject getSecondNearest(int... ids) {
    RSObject cur = null;
    double dist = -1;
    RSTile[] tiles = mineArea.getTileArray();
    for (int x = 0; x < tiles.length; x++) {
            RSObject o = objects.getTopAt(tiles[x]);
        if (o != null) {
        boolean isObject = false;
        for (int id : ids) {
            if (o.getID() == id) {
            isObject = true;
            break;
            }
        }
        if (isObject) {
            double distTmp = calc.distanceBetween(ore.getLocation(), o.getLocation());    

                    String strCurrentRockLoc = ore.getLocation().toString();
                    String strPossRockLoc = o.getLocation().toString();
            if (cur == null && !( o.getLocation().equals(ore.getLocation())) ) {
                        dist = distTmp;
            cur = o;
            }
                    if (distTmp < dist && !( o.getLocation().equals(ore.getLocation())) ) {
                        cur = o;
            dist = distTmp;
            }
        }
            }
    }
    return cur;
}

public boolean onHorizontalOrVertTile(RSTile tile){
    boolean bool = false;    
    if ( getMyPlayer().getLocation().getX() == tile.getX() || getMyPlayer().getLocation().getY() == tile.getY() ) {
        if ( calc.distanceTo(tile) == 1 ) {
            bool = true;
        } else
            bool = false;
    }
    return bool;
}

public void mine() {
    antiBan();
    if ( ore == null) {
        ore = objects.getNearest( rocksID );
        if ( ore != null ) {
            oreLocation = ore.getLocation();
            if ( !calc.tileOnScreen( oreLocation) ) {
                camera.turnToObject(ore);
            }
            if ( !calc.tileOnScreen( oreLocation ) ){
                walking.walkTileMM(oreLocation, 0, 0);
            }
        }
    }
  
    if ( ore != null ) {
        oreLocation = ore.getLocation();
        RSObject tempRock = objects.getTopAt( oreLocation );
        if ( tempRock != null )
            currentID = tempRock.getID();
        else
            ore = null;

        if ( currentID == 37700 || currentID == 37701 || currentID == 37702) {
            if ( nextOre != null ) {
                nextOreLocation = nextOre.getLocation();
                if ( !calc.tileOnScreen( nextOreLocation ) ) {
                    camera.turnToObject(nextOre);
                }
                if ( !calc.tileOnScreen( nextOreLocation ) ){
                    walking.walkTileMM( nextOreLocation, 0, 0 );
                }
                ore = nextOre;
            }
        }

        if ( !(getMyPlayer().isMoving()) && !onHorizontalOrVertTile( oreLocation ) ) {
            ore.doAction("Mine");
        } else if ( getMyPlayer().getAnimation() == -1 && onHorizontalOrVertTile( oreLocation ) ) {
            ore.doAction("Mine");
            camera.moveRandomly(random(800,1000));
        }

        nextOre = getSecondNearest( rocksID );
        
        if (nextOre != null) {
            nextOreLocation = nextOre.getLocation();
            if ( !calc.tileOnScreen( nextOreLocation ) )
                camera.turnToObject(nextOre);  
            mouse.move( calc.tileToScreen( nextOreLocation ), 13, 13 );   
        } else {
            ore = null;
        }

    } 
}
    
public int loop() { 
    if ( game.isLoggedIn() ) {

    if ( inventory.isFull() && atGuild() && !getMyPlayer().isMoving() ) {
        ore = null;
        if ( useCabbagePort ) {
            hasBanked = false;
            cabbagePort();
            sleep(random(1300,2000));
        } else {
            openDoor();
        }
    }

    if ( !(inventory.isFull()) && atGuild() ) {
        mine();
    }

    if ( inventory.isFull() && !useCabbagePort && !atGuild() && !atFallyBank() )
        walking.walkPathMM( walking.findPath(bankTile) );

    if ( !inventory.isFull() && !useCabbagePort && !atGuild() )
        walking.walkPathMM( walking.findPath(doorTile) );

    if ( inventory.isFull() && !atGuild() && !atTheBank() && objects.getTopAt(gateTile) == null ) { 
        if ( useCabbagePort )
            cabbageToBank();
    }

    if (inventory.isFull() && atTheBank() ) {
        passedMusician = false;
        depositOres();
    }

    if ( !useCabbagePort && !atGuild() && !atFallyBank() ) {
        if ( walking.getEnergy() < 20 ) {
            walking.rest();
            walking.setRun(true);
        }
    }

    if ( !useCabbagePort && atFallyBank() && walking.getEnergy() == 100 && !interfaces.get(Bank.INTERFACE_BANK).isValid() )
        walking.walkTileMM( getMyPlayer().getLocation(), 0, 0 );

    if ( useCabbagePort ) {
        if ( !inventory.isFull() && passedMusician && !atGuild() ) {
            walking.walkPathMM( walking.findPath(doorTile) ); 
        }
        if ( !inventory.isFull() && atDraynorBank() && !interfaces.get(Bank.INTERFACE_BANK).isValid() && !getMyPlayer().isMoving() ) {
            cabbagePort();    
            sleep(random(1300,2000));
        }

        if ( getMyPlayer().getLocation().equals(cabbageTile) ) {
            gate = objects.getTopAt(gateTile);
            if (gate != null) {
              log("opening gate");
              gate.doAction("Open Gate");
            }
        }

        if ( atMusician() && walking.getEnergy() < 90 ) {
            walking.rest();
            walking.setRun(true);
            passedMusician = true;
        }
    }

    if ( !(atGuild()) && !(inventory.isFull()) && !(interfaces.get(Bank.INTERFACE_BANK).isValid()) ) {
        if ( useCabbagePort && !atMusician() && !atDraynorBank() && !passedMusician ) {
            if ( atCabbage() && hasBanked )
                walking.walkTileMM(new RSTile(3053, 3284), 1, 0);
            if ( !atCabbage() ) {
                walking.walkPathMM( walking.findPath(musicianTile) );
            }
        }
        openDoorCheck();
    }

    }
    return (random(1000, 2500));
}


public void onFinish() {
    log("Thanks for using it");
    //game.logout(true);
}

public class SCRIPTGUI extends JFrame {

        public SCRIPTGUI() {
        createAndDisplayGUI();
    }

    private void StartButtonActionPerformed(ActionEvent e) {
        dispose();
    }

    private void createAndDisplayGUI() {
                setTitle("Crafting Guild Miner");
        JPanel pane = new JPanel(new BorderLayout());
        JButton start = new JButton("Start");
        start.setActionCommand("Start");
        start.addActionListener(new ButtonListener());
        pane.add(start, BorderLayout.SOUTH);

        Ringbutton = new JCheckBox("Use explorer ring 3?");
        pane.add(Ringbutton, BorderLayout.WEST);
        add(pane);
        pack();
        setVisible(true);
        //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                setLocationRelativeTo(getOwner());
    }

    class ButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            JButton button = (JButton) e.getSource();
            if (e.getActionCommand().equals("Start"))
                dispose();
        }
    }
}

//Paint Details   

    private final Color color1 = new Color(0, 0, 0);
    private final Color color2 = new Color(255, 255, 255);
    private final BasicStroke stroke1 = new BasicStroke(1);

    private final Font font1 = new Font("Arial", Font.BOLD, 16);
    
@Override
public void onRepaint(Graphics g1) {
    Graphics2D g = (Graphics2D)g1;
    if (game.isLoggedIn() ){
        timeRunning = System.currentTimeMillis() - startTime; 
        seconds = timeRunning / 1000;
            
        if (seconds >= 60) { 
            minutes = seconds / 60; 
            seconds -= minutes * 60; 
        } 
        if (minutes >= 60) { 
            hours = minutes / 60; 
            minutes -= hours * 60; 
        }

        expGained = skills.getCurrentExp(Skills.MINING) - startexp;

        if (expGained > 0) {
            expsec = ((float) expGained)/(float)(seconds + (minutes*60) + (hours*60*60));
        }
        expmin = expsec * 60;
        exphour = expmin * 60; 
        int energy = walking.getEnergy();
 
        g.setColor(color1);
        g.setStroke(stroke1);
        g.drawRect(332, 13, 177, 87);
        g.setFont(font1);
        g.setColor(color2);
        g.drawString("Time: " + hours + ":" + minutes + ":" + seconds, 336, 31);
        g.drawString("XP/HR: " + (int) exphour, 336, 53);
        g.drawString("Gold Mined: " + goldMined, 336, 75);
        g.drawString("Silver Mined: " + silverMined, 336, 97);
    }
}


@Override
public void serverMessageRecieved(ServerMessageEvent e) {     
    String message = e.getMessage();

    if (message.contains("mine some silver")) {
        silverMined++;
    }
    if (message.contains("mine some gold")) {
        goldMined++;
    }

    if (message.contains("just found")) {
        gemsFound++;
    }
}

}